package com.yzion.baselib.utils

import android.text.Layout
import android.text.Selection
import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.URLSpan
import android.text.util.Linkify
import android.view.MotionEvent
import android.view.View
import android.widget.TextView
import androidx.annotation.ColorInt
import java.util.regex.Pattern

object HyperLinkHelper {

    private const val REGEX = "(((http[s]?|ftp?|file?)://)?[a-zA-Z0-9.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9.\\-~!@#$%^&*+?:_/=<>]*)?)"

    /**
     * 转换成链接。
     */
    fun transUrlSpan(text: CharSequence, @ColorInt highColor: Int): Spannable {
        val ss = SpannableString.valueOf(text)
        Linkify.addLinks(ss, Pattern.compile(REGEX), "")
        val urlSpans = ss.getSpans(0, ss.length,
            URLSpan::class.java) ?: return ss
        for (sp in urlSpans) {
            val start = ss.getSpanStart(sp)
            val end = ss.getSpanEnd(sp)
            ss.removeSpan(sp)
            ss.setSpan(UrlLinkSpan(sp.url.formatUrl(), highColor), start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
        }
        return ss
    }

    /**
     * 设置点击事件。
     */
    fun setClickListener(spanned: Spanned, listener: UrlLinkSpan.OnClickListener) {
        spanned.getSpans(0, spanned.length, UrlLinkSpan::class.java)
            .forEach { it.listener = listener }
    }

    private fun String.formatUrl(): String {
        return if (indexOf("http") != 0
            && indexOf("ftp") != 0
            && indexOf("file") != 0) {
            "http://$this"
        } else {
            this
        }
    }
    // 并把URLSpan替换成样式需要的Span。
    class UrlLinkSpan(val url: String, @ColorInt val highColor: Int) : ClickableSpan() {

        var listener: OnClickListener? = null

        interface OnClickListener {
            fun onUrlClick(widget: View, url: String)
        }

        override fun onClick(widget: View) {
            listener?.onUrlClick(widget, url)
        }

        override fun updateDrawState(ds: TextPaint) {
            super.updateDrawState(ds)
            ds.color = highColor
            ds.isUnderlineText = true
        }
    }

    //处理textview设置clickableSpan 后于长按事件冲突
    object ClickLinkMovementMethod : LinkMovementMethod() {
        private const val CLICK_DELAY = 500L
        private var lastClickTime: Long = 0
        override fun onTouchEvent(widget: TextView?, buffer: Spannable?, event: MotionEvent?): Boolean {
            event ?: return false
            widget ?: return false
            val action = event.action
            if (action == MotionEvent.ACTION_UP ||
                action == MotionEvent.ACTION_DOWN) {
                var x = event.x.toInt()
                var y = event.y.toInt()
                x -= widget.totalPaddingLeft
                y -= widget.totalPaddingTop
                x += widget.scrollX
                y += widget.scrollY
                val layout: Layout = widget.layout
                val line: Int = layout.getLineForVertical(y)
                val off: Int = layout.getOffsetForHorizontal(line, x.toFloat())
                val link: Array<ClickableSpan> = buffer?.getSpans(off, off, ClickableSpan::class.java)
                    ?: return true
                if (link.isNotEmpty()) {
                    if (action == MotionEvent.ACTION_UP) {
                        if (System.currentTimeMillis() - lastClickTime < CLICK_DELAY) {
                            link[0].onClick(widget)
                        }
                    } else if (action == MotionEvent.ACTION_DOWN) {
                        lastClickTime = System.currentTimeMillis()
                        Selection.setSelection(buffer,
                            buffer.getSpanStart(link[0]),
                            buffer.getSpanEnd(link[0]))
                    }
                    return true
                } else {
                    Selection.removeSelection(buffer)
                }
            }
            return false
        }
    }

}